#include "linkedlisttest.h"

bool LinkedListTest::run() {
    short count=0;

    if (!LinkedListTest::constructorTest())
        std::cout << "ERROR " << ++count << " LinkedListTest::constructorTest() faild!" << std::endl;
    if (!LinkedListTest::addAtEndTest())
        std::cout << "ERROR " << ++count << " LinkedListTest::addAtEndTest() faild!" << std::endl;
    if (!LinkedListTest::addAtStartTest())
        std::cout << "ERROR " << ++count << " LinkedListTest::addAtStartTest() faild!" << std::endl;
    if (!LinkedListTest::getElementAtEndTest())
        std::cout << "ERROR " << ++count << " LinkedListTest::getElementAtEndTest() faild!" << std::endl;
    if (!LinkedListTest::getElementAtStartTest())
        std::cout << "ERROR " << ++count << " LinkedListTest::getElementAtStartTest() faild!" << std::endl;
    if (!LinkedListTest::iteratorTest())
        std::cout << "ERROR " << ++count << " LinkedListTest::iteratorTest1() faild!" << std::endl;
    if (!LinkedListTest::pushTest())
        std::cout << "ERROR " << ++count << " LinkedListTest::pushTest() faild!" << std::endl;
    if (!LinkedListTest::popTest())
        std::cout << "ERROR " << ++count << " LinkedListTest::popTest() faild!" << std::endl;
    if (!LinkedListTest::getSecondLastElementTest())
        std::cout << "ERROR " << ++count << " LinkedListTest::getSecondLastElementTest() faild!" << std::endl;
    if (!LinkedListTest::addAtIteratorPositionTest())
        std::cout << "ERROR " << ++count << " LinkedListTest::addAtIteratorPositionTest() faild!" << std::endl;
    if (!LinkedListTest::deleteAtIteratorPositionTest())
        std::cout << "ERROR " << ++count << " LinkedListTest::deleteAtIteratorPositionTest() faild!" << std::endl;
    if (!LinkedListTest::deleteAndAddAtIteratorPositionTest())
        std::cout << "ERROR " << ++count << " LinkedListTest::deleteAndAddAtIteratorPositionTest() faild!" << std::endl;
    if (!LinkedListTest::iteratorPositionIsCloseToStartTest())
        std::cout << "ERROR " << ++count << " LinkedListTest::iteratorPositionIsCloseToStartTest() faild!" << std::endl;

    return count==0;
}

bool LinkedListTest::constructorTest() {
    LinkedList<double> *testList = new LinkedList<double>();
    delete testList;
    return true;
}

bool LinkedListTest::addAtEndTest() {
    LinkedList<double> *testList = new LinkedList<double>();
    assert((*testList).getSize()==0);
    testList->addAtEnd((*(new double(3.003))));
    assert(testList->getSize()==1);
    (*testList).addAtEnd(*(new double(-3.003)));
    assert(testList->getSize()==2);
    testList->addAtEnd(*(new double(-3.000)));
    assert((*testList).getSize()==3);
    testList->addAtEnd(*(new double(3.003)));
    assert((*testList).getSize()==4);
    testList->addAtEnd(*(new double (9438433.232325436)));
    assert(testList->getSize()==5);

    delete testList;
    return true;
    }

bool LinkedListTest::addAtStartTest() {
    LinkedList<double> *testList = new LinkedList<double>();
    assert((*testList).getSize()==0);
    testList->addAtStart((*(new double(3.003))));
    assert(testList->getSize()==1);
    (*testList).addAtStart(*(new double(-3.003)));
    assert(testList->getSize()==2);
    testList->addAtStart(*(new double(-3.000)));
    assert((*testList).getSize()==3);
    testList->addAtStart(*(new double(3.003)));
    assert((*testList).getSize()==4);
    testList->addAtEnd(*(new double (9438433.232325436)));
    assert(testList->getSize()==5);

    delete testList;
    return true;
}

bool LinkedListTest::getElementAtEndTest() {
    LinkedList<double> *testList = new LinkedList<double>();
    assert((*testList).getSize()==0);
    testList->addAtStart((*(new double(3.003))));
    assert(testList->getElementAtEnd()==3.003);
    assert(testList->getSize()==1);
    (*testList).addAtStart(*(new double(-3.003)));
    assert(testList->getElementAtEnd()==3.003);
    assert(testList->getSize()==2);
    testList->addAtStart(*(new double(-3.000)));
    assert(testList->getElementAtEnd()==3.003);
    assert((*testList).getSize()==3);
    testList->addAtStart(*(new double(3.003)));
    assert(testList->getElementAtEnd()==3.003);
    assert((*testList).getSize()==4);
    testList->addAtEnd(*(new double (9438433.232325436)));
    assert(testList->getSize()==5);
    assert(testList->getElementAtEnd()==9438433.232325436);

    delete testList;
    return true;
}

bool LinkedListTest::getElementAtStartTest() {
    LinkedList<double> *testList = new LinkedList<double>();
    assert((*testList).getSize()==0);
    testList->addAtStart((*(new double(3.003))));
    assert(testList->getElementAtStart()==3.003);
    assert(testList->getSize()==1);
    (*testList).addAtStart(*(new double(-3.003)));
    assert(testList->getElementAtStart()==-3.003);
    assert(testList->getSize()==2);
    testList->addAtStart(*(new double(-3.000)));
    assert(testList->getElementAtStart()==-3.000);
    assert((*testList).getSize()==3);
    testList->addAtStart(*(new double(3.003)));
    assert(testList->getElementAtStart()==3.003);
    assert((*testList).getSize()==4);
    testList->addAtEnd(*(new double (9438433.232325436)));
    assert(testList->getSize()==5);
    assert(testList->getElementAtStart()==3.003);

    delete testList;
    return true;
}

bool LinkedListTest::iteratorTest() {
    LinkedList<double> *testList = new LinkedList<double>();
    assert((*testList).getSize()==0);
    testList->addAtStart((*(new double(3.003))));
    assert(testList->getElementAtStart()==3.003);
    assert(testList->getSize()==1);
    (*testList).addAtStart(*(new double(-3.003)));
    assert(testList->getElementAtStart()==-3.003);
    assert(testList->getSize()==2);
    testList->addAtStart(*(new double(-3.000)));
    assert(testList->getElementAtStart()==-3.000);
    assert((*testList).getSize()==3);
    testList->addAtStart(*(new double(3.003)));
    assert(testList->getElementAtStart()==3.003);
    assert((*testList).getSize()==4);
    testList->addAtEnd(*(new double (9438433.232325436)));
    assert(testList->getSize()==5);
    assert(testList->getElementAtStart()==3.003);

    testList->addAtEnd(*(new double (4823.11)));
    testList->resetIteratorPosition();
    assert(testList->iteratorHasNext());
    assert(testList->iteratorGetNext()==testList->getElementAtStart());
    assert(testList->iteratorHasNext());
    assert(testList->iteratorGetNext()==-3.000);
    assert(testList->iteratorHasNext());
    assert(testList->iteratorGetNext()==-3.003);
    assert(testList->iteratorHasNext());
    assert(testList->iteratorGetNext()==3.003);
    assert(testList->iteratorHasNext());
    assert(testList->iteratorGetNext()==9438433.232325436);
    assert(testList->iteratorHasNext());
    assert(testList->iteratorGetNext()==4823.11);
    assert(testList->iteratorHasNext()==false);

    delete testList;
    return true;
}

bool LinkedListTest::pushTest() {
    LinkedList<double> *testList = new LinkedList<double>();
    testList->push(*(new double(2.22)));
    testList->push(*(new double(2.23)));
    testList->push(*(new double(2.24)));
    testList->push(*(new double(2.25)));

    testList->resetIteratorPosition();
    assert(testList->iteratorHasNext());
    assert(testList->iteratorGetNext()==2.22);
    assert(testList->iteratorGetNext()==2.23);
    assert(testList->iteratorGetNext()==2.24);
    assert(testList->iteratorGetNext()==2.25);
    assert(!testList->iteratorHasNext());

    delete testList;
    return true;
}

bool LinkedListTest::popTest() {
    LinkedList<double> *testList = new LinkedList<double>();
    testList->push(*(new double(2.22)));
    testList->push(*(new double(2.23)));
    testList->push(*(new double(2.24)));
    testList->push(*(new double(2.25)));

    double &temp=testList->pop();
    assert(temp==2.25);
    delete &temp;
    double &temp1=testList->pop();
    assert(temp1=2.24);
    delete &temp1;
    double &temp2=testList->pop();
    assert(temp2=2.23);
    delete &temp2;
    double &temp3=testList->pop();
    assert(temp3=2.22);
    delete &temp3;
    assert(testList->getSize()==0);

    delete testList;
    return true;
}

bool LinkedListTest::getSecondLastElementTest() {
    LinkedList<double> *testList = new LinkedList<double>();
    assert((*testList).getSize()==0);
    testList->addAtStart((*(new double(3.003))));
    testList->addAtStart(*(new double(2)));
    assert(testList->getSecondLastElement()==2);
    assert(testList->getSize()==2);
    (*testList).addAtStart(*(new double(-3.003)));
    assert(testList->getSecondLastElement()==2);
    assert(testList->getSize()==3);
    testList->addAtEnd(*(new double(-3.000)));
    assert(testList->getSecondLastElement()==3.003);
    assert((*testList).getSize()==4);
    testList->addAtStart(*(new double(3.003)));
    assert(testList->getSecondLastElement()==3.003);
    assert((*testList).getSize()==5);
    testList->addAtEnd(*(new double (9438433.232325436)));
    assert(testList->getSize()==6);
    assert(testList->getSecondLastElement()==-3.000);
    delete testList;
    return true;
}

bool LinkedListTest::addAtIteratorPositionTest() {
    LinkedList<double> *testList = new LinkedList<double>();
    testList->addAtStart((*(new double(3.003))));
    testList->addAtStart(*(new double(2)));
    (*testList).addAtStart(*(new double(-3.003)));
    testList->addAtEnd(*(new double(-3.000)));
    testList->addAtStart(*(new double(3.003)));
    testList->addAtEnd(*(new double (9438433.232325436)));

    assert(testList->getSize()==6);
    testList->resetIteratorPosition();
    testList->addAtIteratorPosition(*(new double(3.2)));
    assert(testList->getElementAtStart()==3.2);
    assert(testList->getSize()==7);
    testList->iteratorGetNext();
    testList->addAtIteratorPosition(*(new double(4.7)));
    assert(testList->getSize()==8);
    testList->resetIteratorPosition();
    assert(testList->iteratorGetNext()==3.2);
    assert(testList->iteratorGetNext()==3.003);
    assert(testList->iteratorGetNext()==4.7);
    assert(testList->iteratorGetNext()==-3.003);

    delete testList;
    return true;
}

bool LinkedListTest::deleteAtIteratorPositionTest() {
    LinkedList<double> *testList = new LinkedList<double>();
    testList->addAtStart((*(new double(3.003))));
    testList->addAtStart(*(new double(2)));
    (*testList).addAtStart(*(new double(-3.003)));
    testList->addAtEnd(*(new double(-3.000)));
    testList->addAtStart(*(new double(3.003)));
    testList->addAtEnd(*(new double (9438433.232325436)));

    assert(testList->getSize()==6);
    testList->resetIteratorPosition();
    testList->deleteAtIteratorPosition();
    assert(testList->getElementAtStart()==-3.003);
    assert(testList->getSize()==5);
    testList->iteratorGetNext();
    testList->addAtIteratorPosition(*(new double(4.7)));
    assert(testList->getSize()==6);
    testList->deleteAtIteratorPosition();
    testList->resetIteratorPosition();
    assert(testList->iteratorGetNext()==-3.003);
    assert(testList->iteratorGetNext()==4.7);
    assert(testList->iteratorGetNext()==3.003);
    assert(testList->iteratorGetNext()==-3.000);

    delete testList;
    return true;
}

bool LinkedListTest::deleteAndAddAtIteratorPositionTest() {
    LinkedList<double> *testList = new LinkedList<double>();
    testList->addAtStart(*(new double(0)));
    testList->addAtEnd(*(new double(1)));
    testList->addAtEnd(*(new double(2)));
    testList->addAtEnd(*(new double(3)));
    testList->addAtEnd(*(new double(4)));
    testList->addAtEnd(*(new double(5)));
    testList->addAtEnd(*(new double(6)));
    testList->addAtEnd(*(new double(7)));
    testList->addAtEnd(*(new double(8)));
    testList->addAtEnd(*(new double(9)));

    testList->resetIteratorPosition();
    assert(testList->iteratorGetNext()==0);
    assert(testList->iteratorGetNext()==1);
    assert(testList->iteratorGetNext()==2);

    testList->deleteAtIteratorPosition();
    testList->addAtIteratorPosition(*(new double(3)));
    assert(testList->iteratorGetNext()==4);

    testList->resetIteratorPosition();
    unsigned int i=0;
    while (testList->iteratorHasNext()) {
        // won't run without assertions otherwise
//        assert(testList->iteratorGetNext()==i++);
        if(testList->iteratorGetNext()!=i++) {
            assert(false);
        }
    }

    delete testList;
    return true;
}

bool LinkedListTest::iteratorPositionIsCloseToStartTest() {
        LinkedList<double> *testList = new LinkedList<double>();
    testList->addAtStart(*(new double(0)));
    testList->addAtEnd(*(new double(1)));
    testList->addAtEnd(*(new double(2)));
    testList->addAtEnd(*(new double(3)));
    testList->addAtEnd(*(new double(4)));
    testList->addAtEnd(*(new double(5)));
    testList->addAtEnd(*(new double(6)));
    testList->addAtEnd(*(new double(7)));
    testList->addAtEnd(*(new double(8)));
    testList->addAtEnd(*(new double(9)));

    testList->resetIteratorPosition();
    assert(testList->iteratorPositionIsCloseToStart());
    assert(testList->iteratorGetNext()==0);
    assert(testList->iteratorPositionIsCloseToStart());
    assert(testList->iteratorGetNext()==1);
    assert(!testList->iteratorPositionIsCloseToStart());
    assert(testList->iteratorGetNext()==2);
    assert(!testList->iteratorPositionIsCloseToStart());

    unsigned int i=3;
    while (testList->iteratorHasNext()) {
        // to make it still work, even if we define NDEBUG:
//        assert(testList->iteratorGetNext()==i++);
        if(testList->iteratorGetNext()!=i++) {
            assert(false);
        }
    }

    delete testList;
    return true;
}

